package com.ibm.cps.newmessage;

import java.util.HashMap;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.ibm.cps.message.MessageFields;
import com.ibm.cps.newmessage.MetadataInputSchema.FieldType;
import com.ibm.datamodel.timeseries.TimeSeriesSchema;
import com.ibm.factories.MessageParserFactory;
import com.ibm.interfaces.IMessageParser;
import com.ibm.interfaces.ITimeSeriesSchema;
import com.ibm.util.ErrorCode;
import com.ibm.util.JSONUtility;
import com.ibm.util.exception.CPSException;

public class BasicDataSourceMetadata {
	protected String input;
	protected String schemaString;
	protected String schemaid;
	protected String schemaFormat;
	protected String type;
	protected String dataSourceName;
	protected String tenantid;
	protected HashMap<String, String> key2value;

	public BasicDataSourceMetadata() {

	}
	
	public BasicDataSourceMetadata(String datasourceName, String tenantid, String schemaString, String schemaid, String schemaFormat, String type) throws CPSException{
		this.dataSourceName = datasourceName;
		if (!isValidVariable(dataSourceName)) {
			throw new CPSException(ErrorCode.INVALID_INPUT_ERROR,
					"Invalid datasource name " + dataSourceName + ", it should start with [_|a-z|A-Z]");
		}
		this.tenantid = tenantid;
		this.schemaString = schemaString;
		this.schemaid = schemaid;
		this.schemaFormat = schemaFormat;
		this.type = type;
	}

	public BasicDataSourceMetadata(ObjectNode node) throws CPSException {
		if (getInputMetadataSchema() == null) {
			throw new CPSException(ErrorCode.INTERNAL_ERROR_CODE, "Input metadata schema hasn't been implemented.");
		}
		getInputMetadataSchema().validateInput(node);
		this.input = node.toString();
		this.key2value = JSONUtility.getKeyValue(input);
		this.dataSourceName = key2value.get(MessageFields.NAME);
		if (!isValidVariable(dataSourceName)) {
			throw new CPSException(ErrorCode.INVALID_INPUT_ERROR,
					"Invalid datasource name " + dataSourceName + ", it should start with [_|a-z|A-Z]");
		}
		this.tenantid = key2value.get(MessageFields.TENANTID);
		this.schemaString = key2value.get(MessageFields.SCHEMA);
		this.schemaid = key2value.get(MessageFields.SCHEMAID);
		this.schemaFormat = key2value.get(MessageFields.SCHEMA_FORMAT_TYPE);
		this.type = key2value.get(MessageFields.TYPE);
	}

	public static boolean isValidVariable(String variable) {
		return variable.startsWith("_") || variable.charAt(0) >= 'a' && variable.charAt(0) <= 'z'
				|| variable.charAt(0) >= 'A' && variable.charAt(0) <= 'Z';
	}

	public MetadataInputSchema getInputMetadataSchema() {
		MetadataInputSchema schema = new MetadataInputSchema();
		schema.addField(FieldType.String, MessageFields.SCHEMAID, MessageFields.SCHEMA_FORMAT_TYPE, MessageFields.NAME,
				MessageFields.TYPE, MessageFields.TENANTID);
		schema.addField(FieldType.Array, MessageFields.SCHEMA);
		return schema;
	}

	public String replicate() throws CPSException {
		ObjectNode node = JSONUtility.newObjectNode();
		node.put(MessageFields.SCHEMAID, schemaid);
		node.set(MessageFields.SCHEMA, JSONUtility.fromString(schemaString));
		node.put(MessageFields.SCHEMA_FORMAT_TYPE, schemaFormat);
		node.put(MessageFields.NAME, dataSourceName);
		node.put(MessageFields.PARENTPROCESSORS, dataSourceName);
		return node.toString();
	}

	public ITimeSeriesSchema getTimeSeriesSchema() throws CPSException {
		JsonNode jsonSchema = JSONUtility.fromString(schemaString);
		return new TimeSeriesSchema(tenantid, schemaid, (ArrayNode) jsonSchema, -1);
	}
	
	public IMessageParser getTimeSeriesParser(ITimeSeriesSchema schema) throws CPSException {
		return MessageParserFactory.createMessageParser(this.schemaFormat, schema);
	}

	public String getName() {
		return dataSourceName;
	}

	public String getSchemaid() {
		return schemaid;
	}

	public String getTenantid() {
		return tenantid;
	}

	public String getInput() {
		return input;
	}

	public String getType() {
		return type;
	}

}
